class symbol(object):
    """a class of symbol objects"""

    def __init__(self, name):
        self.name = name
    
    def __eq__(self, other):
        return self.name.__eq__(other.name)

    def __repr__(self):
        return 'S:'+self.name

def set_default(def_sym_class):
    global symbol
    symbol = def_sym_class

def constructor(kwargs):
    constructor = symbol
    if kwargs.has_key('sym_type'):
       constructor = kwargs['sym_type']
    return constructor

def define_module(mod, *symbols, **kwargs):
    """a function that lets you define symbols for a module"""

    symbol_class = constructor(kwargs)

    for symbol_name in symbols:
        sym = symbol_class(symbol_name)
        if isinstance(mod, dict):
           mod[symbol_name] = sym
        else:
           setattr(mod, symbol_name, sym)

def define(*symbols, **kwargs):
    """a decorator that lets your the input function have a list
       of symbols"""

    symbol_class = constructor(kwargs)
    
    def decorator(old_func):
 
        def new_func(*args, **kwargs):
        
            #initalize symbols
            #keep track of overriden variables
            old_globals = {}
            none_globals = {}
        
            f_globals = old_func.func_globals
            #load up the local syms from the attached dict
            for name, local_sym in new_func.local_syms.items():
                if f_globals.has_key(name):
                    old_globals[name] = f_globals[name]
                else:
                    none_globals[name] = True
                f_globals[name] = local_sym
            try:
                ret_val = old_func(*args, **kwargs)
            
            finally:
                #restore previous globals
                for key in old_globals:
                    f_globals[key] = old_globals[key]
                for key in none_globals:
                    del f_globals[key]
        
            return ret_val
        
        #add the local syms to an aux dict attached to the function
        if hasattr(old_func, 'local_syms'):
            for key in symbols:
                old_func.local_syms[key] = symbol_class(key)
            return old_func
        
        new_func.local_syms = {}
        for key in symbols:
            new_func.local_syms[key] = symbol_class(key) 
        return new_func

    return decorator 
